﻿//
// Author: rgy
// Date: 2016-06-06 10:26:58
//


using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using SLua;


public class LuaCoroutine : MonoBehaviour
{
    static LuaCoroutine _instance;
    public static LuaCoroutine Instance
    {
        get
        {
            if (_instance == null)
            {
                GameObject go = new GameObject("~SoarDCoroutine");
                go.AddComponent<LuaCoroutine>().Awake();
            }
            return _instance;
        }
    }
    private bool m_IsAwake = false;

    //lua resume function
    LuaFunction mResumeFunc = null;

    //list of running waitting.
    List<CoroutineDelegate> mDelegates = new List<CoroutineDelegate>();

    class CoroutineDelegate
    {
        public object obj;
        public string name;
        public float delay;
        public float mTimeBegin = 0f;

        //stop by hand
        public bool isStop = false;

        private CoroutineDelegate() { }
        public static CoroutineDelegate create(object o, float t, string n = "")
        {
            CoroutineDelegate instance = new CoroutineDelegate();
            instance.obj = o;
            instance.delay = t;
            instance.name = n;
            //instance.mTimeBegin = Time.realtimeSinceStartup;
            return instance;
        }

        public bool running()
        {
            /*
			if(isStop || Time.realtimeSinceStartup - mTimeBegin >= delay){
				LuaCoroutine.Instance.resumeFunc.Call(obj,!isStop);
				return true;
			}
			*/
            if (isStop || mTimeBegin >= delay)
            {
                LuaCoroutine.Instance.resumeFunc.call(obj, !isStop);
                return true;
            }
            mTimeBegin += Time.deltaTime;
            return false;
        }
    }

    void Awake()
    {
        if (m_IsAwake) return;
        m_IsAwake = true;

        if (_instance != null)
        {
            DestroyImmediate(this.gameObject);
            return;
        }
        _instance = this;
        DontDestroyOnLoad(this.gameObject);

    }

    // Update is called once per frame
    void Update()
    {
        for (int i = 0; i < mDelegates.Count;)
        {
            if (mDelegates[i].running())
            {
                mDelegates.RemoveAt(i);
                continue;
            }
            i++;
        }
    }

    LuaFunction resumeFunc
    {
        get
        {
            if (mResumeFunc == null)
            {
                mResumeFunc = (LuaFunction)LuaState.main["ResumeCoroutine"];
            }
            return mResumeFunc;
        }
    }

    ///<summary>
    ///	添加一个Coroutine计时器
    ///</summary>
    public static void WaitForSeconds(object o, float time, string name = "")
    {
        LuaCoroutine.Instance.AddWait(o, time, name);
    }

    public static void StopCoroutineByName(string name = "")
    {
        if (string.IsNullOrEmpty(name)) return;
        LuaCoroutine.Instance.Stop(name);
    }

    private void AddWait(object o, float t, string name = "")
    {
        mDelegates.Add(CoroutineDelegate.create(o, t, name));
    }

    private void Stop(string n)
    {
        for (int i = 0; i < mDelegates.Count; i++)
        {
            if (mDelegates[i].name == n) { mDelegates[i].isStop = true; }
        }
    }
}
